﻿#if VISTADB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using VistaDB.Provider;
using VistaDB;
using System.Text;
using System.Reflection;

namespace PTA.Db
{
    /// <summary>
    /// 访问Firebird的数据库的命令
    /// </summary>
    public class VistaDBDataCommand : DataCommand<VistaDBParameter>
    {
        private const string PARAMETERPREFIX = "@";
        protected override string ParameterPrefix
        {
            get 
            {
                return PARAMETERPREFIX; 
            }
        }

        public VistaDBDataCommand() { }

        public VistaDBDataCommand(string commandText) : base(commandText) { }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="commandText">数据库命令文本</param>
        /// <param name="commandType">数据库命令类型</param>
        /// <param name="parameters">数据库命令参数</param>
        public VistaDBDataCommand(string commandText, CommandType commandType, VistaDBParameter[] parameters) :
            base(commandText, commandType, parameters) { }

        public VistaDBParameter AddIn(string name, VistaDBType type)
        {
            return this.Add(new VistaDBParameter(WrapParameterName(name), type));
        }

        public VistaDBParameter AddIn(string name, VistaDBType type, int size)
        {
            return this.Add(new VistaDBParameter(WrapParameterName(name), type, size));
        }

        public VistaDBParameter AddIn(string name, VistaDBType type, int size, object value)
        {
            return this.Add(new VistaDBParameter(WrapParameterName(name), type, size) { Value = value });
        }

        public VistaDBParameter AddIn(string name, VistaDBType type, object value)
        {
            return this.Add(new VistaDBParameter(WrapParameterName(name), type) { Value = value });
        }

        public VistaDBParameter Add(string name, object value, VistaDBType type, ParameterDirection direction, int size)
        {
            return this.Add(new VistaDBParameter(WrapParameterName(name), type, size) { Direction = direction, Value = value });
        }

        public VistaDBParameter AddOut(string name, VistaDBType type)
        {
            var p = new VistaDBParameter(WrapParameterName(name), type) { Direction = ParameterDirection.Output };
            this.parameters.Add(p);
            return p;
        }

        public VistaDBParameter AddOut(string name, VistaDBType type, int size)
        {
            var p = new VistaDBParameter(WrapParameterName(name), type, size) { Direction = ParameterDirection.Output };
            this.parameters.Add(p);
            return p;
        }

        public void AddReturn(string name, VistaDBType type)
        {
            this.parameters.Add(new VistaDBParameter(name, type) { Direction = ParameterDirection.ReturnValue });
        }

        public void AddReturn(string name, VistaDBType type, int size)
        {
            this.parameters.Add(new VistaDBParameter(name, type, size) { Direction = ParameterDirection.ReturnValue });
        }
    }

    /// <summary>
    /// Firebird数据库访问类
    /// </summary>
    public class VistaDBDataAccess : DataAccess<VistaDBConnection, VistaDBDataAdapter, VistaDBTransaction, VistaDBParameter, VistaDBDataCommand>
    {
        /// <summary>
        /// 默认的构造函数
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        public VistaDBDataAccess(string connectionString)
            : base(connectionString)
        {
        }

        /// <summary>
        /// 默认的构造函数
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        public VistaDBDataAccess(string connectionString, bool enablelog)
            : base(connectionString)
        {
            this.WriteDebug = enablelog;
        }


        /// <summary>
        /// 默认的构造函数
        /// </summary>
        /// <param name="connectionBuilder">数据库连接字符串生成器</param>
        public VistaDBDataAccess(VistaDBConnectionStringBuilder connectionBuilder) :
            this(connectionBuilder.ConnectionString)
        {
        }

        /// <summary>
        /// 默认的构造函数
        /// </summary>
        /// <param name="connectionBuilder">数据库连接字符串生成器</param>
        public VistaDBDataAccess(VistaDBConnectionStringBuilder connectionBuilder, bool enablelog) :
            this(connectionBuilder.ConnectionString)
        {
            this.WriteDebug = enablelog;
        }

        /// <summary>
        /// 获取存储过程的参数
        /// </summary>
        /// <param name="procName">存储过程名称</param>
        /// <returns>存储过程的参数</returns>
        protected override VistaDBParameter[] GetProcParameters(string procName)
        {
            VistaDBParameter[] pvs = GrabParameters(procName);
            if (pvs == null)
            {
                using (VistaDBCommand cmd = new VistaDBCommand(procName, CreateConnection()))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Connection.Open();
                    VistaDBCommandBuilder.DeriveParameters(cmd);
                    cmd.Connection.Dispose();
                    cmd.Parameters.RemoveAt(0);
                    pvs = new VistaDBParameter[cmd.Parameters.Count];
                    cmd.Parameters.CopyTo(pvs, 0);
                    SaveParameters(procName, pvs);
                    pvs = GrabParameters(procName);
                }
            }
            return pvs;
        }

        public override void Insert(BaseEntity m)
        {
            var cmd = this.CreateCommand();
            EntityInfo ea = EntityHelper.GetEntityAttribute(m.GetType());
            bool hasfield = false;
            cmd.CommandText = "INSERT INTO " + ea.DataTable + " (";
            StringBuilder sbvalue = new StringBuilder("VALUES (");
            int pidx = 1;
            foreach (var item in ea.Properties)
            {
                if ((item.Value.PropertyAttribute.Flag & BindingFlag.Insert) > 0)
                {
                    if (item.Value.PropertyAttribute.Identity) //如果使用Identity则跳过这个节点。
                    {
                        continue;
                    }
                    cmd.CommandText = cmd.CommandText + (hasfield ? ", " : string.Empty);
                    sbvalue.Append(hasfield ? ", " : string.Empty);
                    string pname = "@" + pidx;
                    cmd.AddIn(pname, item.Value.PropertyInfo.GetValue(m, null));
                    cmd.CommandText = cmd.CommandText + item.Value.PropertyAttribute.Name;
                    sbvalue.Append(pname);

                    pidx++;
                    hasfield = true;
                }
            }
            if (!hasfield)
            {
                throw new Exception(String.Format("没有为{0}类型的实体设置要插入数据库的字段", m.GetType().FullName));
            }
            cmd.CommandText = cmd.CommandText + " ) ";
            sbvalue.Append(")");

            cmd.CommandText = cmd.CommandText + sbvalue.ToString();
            cmd.CommandType = CommandType.Text;
            this.ExecuteNonQuery(cmd);
        }

#region 参数管理

        /// <summary>
        /// 创建数据库命令参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="type">参数类型</param>
        /// <returns>数据库命令参数</returns>
        public VistaDBParameter MakeIn(string name, VistaDBType type)
        {
            return new VistaDBParameter(name, type);
        }

        /// <summary>
        /// 创建数据库命令参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="type">参数类型</param>
        /// <param name="size">参数长度</param>
        /// <returns>数据库命令参数</returns>
        public VistaDBParameter MakeIn(string name, VistaDBType type, int size)
        {
            return new VistaDBParameter(name, type, size);
        }

        /// <summary>
        /// 创建数据库命令参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="value">参数值</param>
        /// <param name="type">参数类型</param>
        /// <param name="size">参数长度</param>
        /// <returns>数据库命令参数</returns>
        public VistaDBParameter MakeIn(string name, VistaDBType type, int size, object value)
        {
            VistaDBParameter p = new VistaDBParameter(name, type, size);
            p.Value = value;
            return p;
        }

        /// <summary>
        /// 创建数据库命令参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="type">参数类型</param>
        /// <returns>数据库命令参数</returns>
        public VistaDBParameter MakeOut(string name, VistaDBType type)
        {
            VistaDBParameter p = new VistaDBParameter(name, type);
            p.Direction = ParameterDirection.Output;
            return p;
        }

        /// <summary>
        /// 创建数据库命令参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="size">参数长度</param>
        /// <param name="type">参数类型</param>
        /// <returns>数据库命令参数</returns>
        public VistaDBParameter MakeOut(string name, VistaDBType type, int size)
        {
            VistaDBParameter p = new VistaDBParameter(name, type, size);
            p.Direction = ParameterDirection.Output;
            return p;
        }

        /// <summary>
        /// 创建数据库命令参数
        /// </summary>
        /// <param name="name">参数名称</param>
        /// <param name="value">参数值</param>
        /// <param name="type">参数类型</param>
        /// <param name="size">参数长度</param>
        /// <param name="direction">参数方向</param>
        /// <returns>数据库命令参数</returns>
        public VistaDBParameter MakeParam(string name, object value, VistaDBType type, ParameterDirection direction, int size)
        {
            VistaDBParameter p = new VistaDBParameter(name, type);
            if (value != null)
            {
                p.Value = value;
            }
            if (size > 0)
            {
                p.Size = size;
            }
            p.Direction = direction;
            return p;
        }

#endregion
    }
}

#endif